
package com.idealighter.game.games.weishuwu.manager;

import com.alibaba.fastjson.JSONObject;

import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.chat.manager.ChatMsgMgr;
import com.idealighter.game.core.common.Game;
import com.idealighter.game.core.constant.BoolInteger;
import com.idealighter.game.core.constant.notice.NoticeType;
import com.idealighter.game.dictionary.dic.GameNoticeDic;
import com.idealighter.game.dictionary.dic.WeishuwuRoomDic;
import com.idealighter.game.dictionary.dic.WeishuwuRoomTypeDic;
import com.idealighter.game.dictionary.domain.WeishuwuRoomDomain;
import com.idealighter.game.dictionary.domwrapper.GameNoticeDomainWrapper;
import com.idealighter.game.gamehall.dto.MemInfo;
import com.idealighter.game.games.common.AbstractRoom;
import com.idealighter.game.games.common.AbstractSeat;
import com.idealighter.game.games.common.AbstractTable;
import com.idealighter.game.games.common.RoomState;
import com.idealighter.game.games.weishuwu.dto.BetInfo;
import com.idealighter.game.games.weishuwu.dto.CardsInfo;
import com.idealighter.game.games.weishuwu.dto.RoomInfo;
import com.idealighter.game.games.weishuwu.dto.RoomTypeDetailInfo;
import com.idealighter.game.games.weishuwu.message.ResApplyBankersMsg;
import com.idealighter.game.games.weishuwu.message.ResBalanceMsg;
import com.idealighter.game.games.weishuwu.message.ResBankerInfoMsg;
import com.idealighter.game.games.weishuwu.message.ResBetMsg;
import com.idealighter.game.games.weishuwu.message.ResChipsChangeMsg;
import com.idealighter.game.games.weishuwu.message.ResClearBetMsg;
import com.idealighter.game.games.weishuwu.message.ResDealCardsMsg;
import com.idealighter.game.games.weishuwu.message.ResEnterGameHallMsg;
import com.idealighter.game.games.weishuwu.message.ResEnterRoomMsg;
import com.idealighter.game.games.weishuwu.message.ResEnterTableMsg;
import com.idealighter.game.games.weishuwu.message.ResExitRoomMsg;
import com.idealighter.game.games.weishuwu.message.ResExitTableMsg;
import com.idealighter.game.games.weishuwu.message.ResFastEnterTableMsg;
import com.idealighter.game.games.weishuwu.message.ResHistoryMsg;
import com.idealighter.game.games.weishuwu.message.ResOtherEnterTableMsg;
import com.idealighter.game.games.weishuwu.message.ResResultMsg;
import com.idealighter.game.games.weishuwu.message.ResTableBetMsg;
import com.idealighter.game.games.weishuwu.message.ResTimeMsg;
import com.idealighter.game.games.weishuwu.struct.BettingDecision;
import com.idealighter.game.games.weishuwu.struct.WeishuwuCard;
import com.idealighter.game.games.weishuwu.struct.WeishuwuCardsType;
import com.idealighter.game.games.weishuwu.struct.WeishuwuRoom;
import com.idealighter.game.games.weishuwu.struct.WeishuwuSeat;
import com.idealighter.game.games.weishuwu.struct.WeishuwuTable;
import com.idealighter.game.games.weishuwu.util.CardsTypeGetter;
import com.idealighter.game.message.core.ResMessage;
import com.idealighter.game.notice.manager.NoticeMsgMgr;
import com.idealighter.game.player.manager.PlayerMsgWriter;
import com.idealighter.game.player.struct.Player;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;

/**
 * 魏蜀吴消息管理 .
 * 
 */
@Singleton
public class WeishuwuMsgMgr {

  @Inject
  private PlayerMsgWriter msgWriter;
  @Inject
  private WeishuwuDataMgr dataMgr;
  @Inject
  private WeishuwuRoomDic roomDic;
  @Inject
  private WeishuwuRoomTypeDic roomTypeDic;
  @Inject
  private NoticeMsgMgr msgMgr;
  @Inject
  private GameNoticeDic gameNoticeDic;
  @Inject
  private ChatMsgMgr chatMsgMgr;

  /**
   * 发送进入游戏大厅消息.
   * 
   * @param player 玩家.
   */
  public void sendEnterGameHallMsg(Player player) {
    ResEnterGameHallMsg msg = new ResEnterGameHallMsg();

    Collection<WeishuwuRoom> rooms = dataMgr.rooms();
    for (WeishuwuRoom room : rooms) {
      WeishuwuRoomDomain roomDom = roomDic.get(room.getId().intValue());
      if (roomDom.getIsActive() != 1) {
        continue;
      }
      RoomTypeDetailInfo roomTypeDetailInfo = new RoomTypeDetailInfo();

      roomTypeDetailInfo.setType(roomDom.getType());
      roomTypeDetailInfo.setTypeName(roomTypeDic.map().get(roomDom.getType()).getName());

      RoomInfo roomInfo = new RoomInfo();
      roomInfo.setRoomId(room.getId().intValue());
      roomInfo.setName(roomDom.getName());
      roomInfo.setType(roomDom.getType());
      roomInfo.setMaxNum(roomDom.getMaxNum());
      roomInfo.setFree(roomDom.getFree());
      roomInfo.setGeneral(roomDom.getGeneral());
      roomInfo.setCrowded(roomDom.getCrowded());
      roomInfo.setLower(roomDom.getLower());
      roomInfo.setUpper(roomDom.getUpper());
      roomInfo.setProportionGold(roomDom.getProportionGold());
      roomInfo.setProportionChips(roomDom.getProportionChips());
      roomInfo.setTabble(roomDom.getTable());
      roomInfo.setMaxOne(roomDom.getMaxOne());
      roomInfo.setMinOne(roomDom.getMinOne());
      roomInfo.setAfee(roomDom.getAfee());
      roomInfo.setInType(roomDom.getInType());
      roomInfo.setPlayerNum(room.getPlayers().size());
      roomInfo.setStatus(roomStatus(room).desc);
      roomInfo.setDisplayNames(roomDom.getDisplays());
      roomInfo.setPlaceHolder(roomDom.getPlaceHolder());
      roomTypeDetailInfo.getRooms().add(roomInfo);

      msg.getRoomTypes().add(roomTypeDetailInfo);
    }

    msgWriter.writeMsg(player, msg);
  }

  /**
   * 房间状态，空闲,普通,拥挤,爆满.
   * 
   * @param room .
   * @return
   */
  private RoomState roomStatus(WeishuwuRoom room) {
    int playersNum = room.getPlayers().size();
    WeishuwuRoomDomain roomDom = roomDic.get(room.getId().intValue());

    if (playersNum < roomDom.getMaxNum() * roomDom.getFree() / 100) {
      return RoomState.IDLE;
    } else if (playersNum < roomDom.getMaxNum() * roomDom.getGeneral() / 100) {
      return RoomState.GENERAL;
    } else if (playersNum < roomDom.getMaxNum() * roomDom.getCrowded() / 100) {
      return RoomState.CROWD;
    } else {
      return RoomState.FULL;
    }

  }

  /**
   * 发送兑换筹码消息.
   * 
   * @param seat 座位信息.
   */
  public void sendChipsChangeMsg(WeishuwuSeat seat) {
    ResChipsChangeMsg msg = new ResChipsChangeMsg();
    msg.setChips(seat.getTotalChips());
    msg.setPlayerId(seat.getPlayerId());
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送进入桌子消息.
   * 
   * @param player 玩家.
   */
  public void sendEnterRoomMsg(Player player) {
    ResEnterRoomMsg msg = new ResEnterRoomMsg();
    for (AbstractTable table : player.curRoom.tables()) {
      msg.getTables().add(table.tableInfo());
    }
    msg.setMembers(player.curRoom.memInfos());
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送进入桌子消息 .
   * 
   * @param player 玩家.
   * @param table .
   */
  public void sendEnterTableMsg(Player player, AbstractTable table) {
    ResEnterTableMsg msg = new ResEnterTableMsg();
    AbstractRoom room = table.room();
    List<MemInfo> mems = new ArrayList<>();
    for (Long playerId : table.players()) {
      mems.add(room.memInfo(playerId));
    }
    msg.setMems(mems);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送退出房间消息.
   * 
   * @param player 玩家.
   * @param res 0:退出成功,1:在牌桌中退出失败
   */
  public void sendExitRoomMsg(Player player, int res) {
    ResExitRoomMsg msg = new ResExitRoomMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发牌.
   * 
   * @param table .
   */
  public void sendDealCardsMsg(WeishuwuTable table) {

    CardsInfo cardsInfoBanker = new CardsInfo();
    cardsInfoBanker.setId(0);
    // 庄家牌
    WeishuwuCardsType cardType = CardsTypeGetter.getCardsType(table.banker.subList(0, 2));
    cardsInfoBanker.setCardsType(cardType.type);
    for (WeishuwuCard card : table.banker) {
      cardsInfoBanker.getCards().add(card.ordinal());
    }
    ResDealCardsMsg msg = new ResDealCardsMsg();
    msg.getCardsInfo().add(cardsInfoBanker);

    // 闲家牌
    CardsInfo cardsInfoPlayer = new CardsInfo();
    WeishuwuCardsType cardTypePlayer =
        CardsTypeGetter.getCardsType(table.normalPlayer.subList(0, 2));
    cardsInfoPlayer.setCardsType(cardTypePlayer.type);
    cardsInfoPlayer.setId(1);
    for (WeishuwuCard card : table.normalPlayer) {
      cardsInfoPlayer.getCards().add(card.ordinal());
    }

    msg.getCardsInfo().add(cardsInfoPlayer);
    for (WeishuwuSeat seat1 : table.seats) {
      if (seat1.getPlayerId() == 0) {
        continue;
      }
      msgWriter.writeMsg(seat1.getPlayerId(), msg);
    }
  }

  /**
   * 发送退出桌子消息.
   * 
   * @param seat 座位信息.
   */
  public void sendExitTableMsg(WeishuwuSeat seat) {
    ResExitTableMsg msg = new ResExitTableMsg();
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送其他人进入桌子消息.
   * 
   * @param seat 座位信息.
   */
  public void sendOtherEnterTableMsg(WeishuwuSeat seat) {
    ResOtherEnterTableMsg msg = new ResOtherEnterTableMsg();
    msg.setMem(seat.table.room.memInfo(seat.getPlayerId()));
    for (Long playerId : seat.table.players()) {
      if (playerId != seat.getPlayerId()) {
        msgWriter.writeMsg(playerId, msg);
      }
    }
  }

  /**
   * 发送快速进入结果消息.
   * 
   * @param player 玩家.
   * @param res 0:成功,1:没有空位置
   */
  public void sendFastEnterTableMsg(Player player, int res) {
    ResFastEnterTableMsg msg = new ResFastEnterTableMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 向同桌的玩家(包括自己)发送消息.
   * 
   * @param table .
   * @param msg .
   */
  public void sendTablePlayersMsg(WeishuwuTable table, ResMessage msg) {
    List<? extends AbstractSeat> seats = table.seats();
    for (int i = 0; i < seats.size(); i++) {
      AbstractSeat seat = seats.get(i);
      long playerId = seat.getPlayerId();
      if (playerId > 0) {
        msgWriter.writeMsg(playerId, msg);
      }
    }
  }

  /**
   * 图标合计押注.
   * 
   * 
   * @param player 玩家.
   * @param area .
   * @param chips .
   * 
   */
  public void sendBetMsg(Player player, int area, long chips) {
    ResBetMsg msg = new ResBetMsg();
    msg.setArea(area);
    msg.setChips(chips);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 清空下注.
   * 
   * @param player 玩家.
   * @param res 结果(0:成功,1:下注阶段不能清除下注).
   */
  public void sendClearBetMsg(Player player, int res) {
    ResClearBetMsg msg = new ResClearBetMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);

  }

  /**
   * 同步桌上筹码 . 发送下注信息.
   * 
   * @param table .
   */
  public void sendTableBetInfosMsg(WeishuwuTable table) {
    ResTableBetMsg msg = new ResTableBetMsg();
    for (int i = 0; i <= 8; i++) {
      BetInfo betInfo = new BetInfo();
      betInfo.setArea(i);
      betInfo.setChips(table.tableBets().getOrDefault(i, 0L));
      msg.getBetInfo().add(betInfo);
    }

    // for (Entry<Integer, Long> tableBet : table.tableBets().entrySet()) {
    // BetInfo betInfo = new BetInfo();
    // betInfo.setArea(tableBet.getKey());
    // betInfo.setChips(tableBet.getValue());
    // msg.getBetInfo().add(betInfo);
    // }
    sendTablePlayersMsg(table, msg);
  }

  /**
   * 同步桌上筹码 . 发送下注信息.
   * 
   * @param seat 座位信息.
   */
  public void sendTableBetInfosMsg(WeishuwuSeat seat) {
    ResTableBetMsg msg = new ResTableBetMsg();
    for (Entry<Integer, Long> tableBet : seat.table.tableBets().entrySet()) {
      BetInfo betInfo = new BetInfo();
      betInfo.setArea(tableBet.getKey());
      betInfo.setChips(tableBet.getValue());
      msg.getBetInfo().add(betInfo);
    }
    msgWriter.writeMsg(seat.getPlayerId(), msg);
  }

  /**
   * 发送庄家信息.
   * 
   * @param table .
   */
  public void sendBankerInfoMsg(WeishuwuTable table) {
    WeishuwuSeat banker = table.banker();
    ResBankerInfoMsg msg = new ResBankerInfoMsg();
    msg.setPlayerId(banker.getPlayerId());
    if (banker.getPlayerId() == 0) {
      msg.setSex(3);
    } else {
      msg.setSex(banker.getSex());
    }
    msg.setChips(banker.getTotalChips());
    msg.setName(banker.getPlayerName());
    msg.setNum(banker.bankerNum);
    msg.setScore(banker.bankerScore);
    sendTablePlayersMsg(table, msg);

  }

  /**
   * 发送庄家信息 .
   * 
   * @param seat 座位信息.
   */
  public void sendBankerInfoMsg(WeishuwuSeat seat) {
    WeishuwuSeat banker = seat.table.banker();
    ResBankerInfoMsg msg = new ResBankerInfoMsg();
    msg.setPlayerId(banker.getPlayerId());
    msg.setPlayerId(banker.getPlayerId());
    if (banker.getPlayerId() == 0) {
      msg.setSex(3);
    } else {
      msg.setSex(banker.getSex());
    }
    msg.setChips(banker.getTotalChips());
    msg.setName(banker.getPlayerName());
    msg.setNum(banker.bankerNum);
    msg.setScore(banker.bankerScore);
    msgWriter.writeMsg(seat.getPlayerId(), msg);
  }

  /**
   * 发送申请庄家列表(所有玩家).
   * 
   * @param table .
   */
  public void sendApplyBankersMsg(WeishuwuTable table) {
    ResApplyBankersMsg msg = new ResApplyBankersMsg();
    msg.setApplicants(new ArrayList<>(table.applyBankers));
    sendTablePlayersMsg(table, msg);

  }

  /**
   * 发送申请庄家列表(单个玩家).
   * 
   * @param seat 座位信息.
   */
  public void sendApplyBankersMsg(WeishuwuSeat seat) {
    ResApplyBankersMsg msg = new ResApplyBankersMsg();
    msg.setApplicants(new ArrayList<>(seat.table.applyBankers));
    msgWriter.writeMsg(seat.getPlayerId(), msg);

  }

  /**
   * 发送给客户端当前游戏阶段.
   * 
   * @param table .
   * @param time .
   */
  public void sendGameStage(WeishuwuTable table, int time) {
    ResTimeMsg msg = new ResTimeMsg();
    msg.setTime(time);
    // System.err.println(time);
    msg.setState(table.status.val);
    sendTablePlayersMsg(table, msg);

  }

  /**
   * 发送给客户端当前游戏阶段 .
   * 
   * @param seat 座位信息.
   * @param time .
   */
  public void sendGameStage(WeishuwuSeat seat, int time) {
    ResTimeMsg msg = new ResTimeMsg();
    msg.setTime(time);
    // System.err.println(time);
    msg.setState(seat.table.status.val);
    msgWriter.writeMsg(seat.getPlayerId(), msg);

  }

  /**
   * 发送历史记录.
   * 
   * @param table .
   */
  public void sendHistory(WeishuwuTable table) {
    ResHistoryMsg msg = new ResHistoryMsg();
    ArrayList<Integer> waybill = new ArrayList<>(table.history);
    ArrayList<Integer> winhis = new ArrayList<>(table.win);
    ArrayList<Integer> hero = new ArrayList<>(table.hero);
    // Collections.reverse(histroy);
    // msg.setResult(histroy);
    msg.setWaybill(waybill);
    msg.setWin(winhis);
    msg.setHero(hero);
    sendTablePlayersMsg(table, msg);

  }

  /**
   * 发送历史记录.
   * 
   * @param seat 座位信息.
   */
  public void sendHistory(WeishuwuSeat seat) {
    ResHistoryMsg msg = new ResHistoryMsg();
    ArrayList<Integer> waybill = new ArrayList<>(seat.table.history);
    ArrayList<Integer> winhis = new ArrayList<>(seat.table.win);
    ArrayList<Integer> hero = new ArrayList<>(seat.table.hero);
    // Collections.reverse(histroy);
    msg.setWaybill(waybill);
    msg.setWin(winhis);
    msg.setHero(hero);
    msgWriter.writeMsg(seat.getPlayerId(), msg);

  }

  /**
   * 结算消息.
   * 
   * @param seat 座位信息.
   */
  public void sendBanlance(WeishuwuSeat seat) {
    ResBalanceMsg msg = new ResBalanceMsg();
    WeishuwuSeat bankerSeat = seat.table.banker();
    msg.setBankerChips(bankerSeat.billChips);
    msg.setPlayerChips(seat.billChips);
    msgWriter.writeMsg(seat.getPlayerId(), msg);

  }

  /**
   * 如果满足条件发送庄家通吃通赔公告.
   * 
   * @param playerName 牌型.
   * @param roomName 房间名字.
   * @param count .
   * @param chips 赢得筹码.
   */
  public void sendBankerNotice(String playerName, String roomName, int count, long chips) {
    for (GameNoticeDomainWrapper dom : gameNoticeDic.getGameDoms()
        .get(Game.BAIREN_NIUNIU.getType())) {
      JSONObject conditionData = dom.conditionData();
      // 公告条件牌型
      Integer conditionCardType = conditionData.getInteger("cardsType");

      if (-conditionCardType == count) {
        String sendContent = MessageFormat.format(dom.getContent(), playerName, chips, roomName);
        if (dom.getMarqueeShow() == BoolInteger.TRUE) { // 跑马灯公告
          msgMgr.sendMarqueeNoticeMsg(sendContent, NoticeType.GAME, dom.getInterval(),
              dom.getTimes(), dom.getColor());
        }

        if (dom.getChatShow() == BoolInteger.TRUE) { // 聊天公告
          chatMsgMgr.sendSysNoticeMsg(sendContent);
        }
      }
    }
  }

  /**
   * 发送开出结果.
   * 
   * @param table .
   */
  public void sendRewardResult(WeishuwuTable table) {
    ResResultMsg msg = new ResResultMsg();
    List<Integer> li = Lists.newArrayList();
    for (BettingDecision val : table.result) {
      li.add(val.type);
    }
    msg.getResult().addAll(li);
    sendTablePlayersMsg(table, msg);
  }
}
